﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ServiceModel.Syndication;
using System.Text.RegularExpressions;

namespace RssReader
{
    public class RssReader : IRssReader
    {
        #region Fields
        public String ErrorStatus { get; set; }
        Dictionary<string, string> BasicsParent;
        #endregion

        #region Functions
        private string TryToDisplayCategory(List<SyndicationCategory> category)
        {
            if (category.Count != 0) return (category[0].Name);
            else return ("Unknown");
        }

        private string TryToDisplayLink(List<SyndicationLink> link)
        {
            if (link.Count != 0) return (link[0].Uri.ToString());
            else return ("Unknown");
        }

        private string TryToDisplayAuthor(List<SyndicationPerson> author)
        {
            if (author.Count != 0) return (author[0].Name);
            else return ("Unknown");
        }

        private string convertsummary(string value)
        {
            if (String.IsNullOrWhiteSpace(value)) return null;

            int maxLength = 300, strLength = 0;
            string fixedString = "";
            fixedString = Regex.Replace(value.ToString(), "<[^>]+>", string.Empty);
            fixedString = fixedString.Replace("\r", "").Replace("\n", "");
            strLength = fixedString.ToString().Length;
            if (strLength == 0) return null;
            else if (strLength >= maxLength)
            {
                fixedString = fixedString.Substring(0, maxLength);
                fixedString = fixedString.Substring(0, fixedString.LastIndexOf(" "));
            }
            fixedString += "..";
            return fixedString;
        }

        private void FillBasicsFeedsMap()
        {
            BasicsParent = new Dictionary<string, string>();
            BasicsParent.Add("http://www.20minutes.fr/rss/une.xml", "NEWS");
            BasicsParent.Add("http://rss.lefigaro.fr/lefigaro/laune?format=xml", "NEWS");
            BasicsParent.Add("http://www.lemonde.fr/rss/sequence/0,2-3208,1-0,0.xml", "NEWS");
            BasicsParent.Add("http://tf1.lci.fr/xml/rss/0,,10,00.xml", "NEWS");
            BasicsParent.Add("http://syndication.lesechos.fr/rss/rss_inter.xml", "NEWS");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/HomePage", "NEWS");
            BasicsParent.Add("http://rss.feedsportal.com/c/268/f/3632/index.rss", "ECONOMY");
            BasicsParent.Add("http://www.easybourse.com/RSS/easybourse-actualite.rss", "ECONOMY");
            BasicsParent.Add("http://forex.fr/index2.php?option=ds-syndicate&version=1&feed_id=1", "ECONOMY");
            BasicsParent.Add("http://www.nytimes.com/services/xml/rss/nyt/GlobalBusiness.xml", "ECONOMY");
            BasicsParent.Add("http://www.absolut-photo.com/news/rss/", "VARIOUS");
            BasicsParent.Add("http://www.atypictural.com/rss.xml", "VARIOUS");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/NYRegion", "VARIOUS");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/Travel", "VARIOUS");
            BasicsParent.Add("http://www.comment-economiser.fr/rss-radin-malin.php", "VARIOUS");
            BasicsParent.Add("http://feeds.feedburner.com/GagnerDesSous", "VARIOUS");
            BasicsParent.Add("http://feeds.feedburner.com/Leblogvendeesign", "MEDIA");
            BasicsParent.Add("http://www.generation-nt.com/export/rss_matos.xml", "MEDIA");
            BasicsParent.Add("http://www.3dvf.com/modules/news/rss.php", "MEDIA");
            BasicsParent.Add("http://www.videotubes.fr/?feed=rss2", "MEDIA");
            BasicsParent.Add("http://wheels.blogs.nytimes.com/feed/", "RECREATION");
            BasicsParent.Add("http://www.lamoooche.com/getRSS.php?idnews=4311", "RECREATION");
            BasicsParent.Add("http://www.lamoooche.com/getRSS.php?idnews=1648", "RECREATION");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/Technology", "HIGH-TECH");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/internet", "HIGH-TECH");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/start-ups", "HIGH-TECH");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/Environment", "HIGH-TECH");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/Space", "HIGH-TECH");
            BasicsParent.Add("http://feeds1.nytimes.com/nyt/rss/Sports", "SPORT");
            BasicsParent.Add("http://feeds.nytimes.com/nyt/rss/Tennis", "SPORT");
            BasicsParent.Add("http://www.eurosport.fr/z/hiver/rss.xml", "SPORT");
            BasicsParent.Add("http://www.mondialfoot2010.org/fr/?feed=rss2", "SPORT");
            BasicsParent.Add("http://www.ma-reduc.com/rss.php?cat=charme", "CHARM");
            BasicsParent.Add("http://www.gonnalove.com/gonna/rss/gonnalove-rss.xml", "CHARM");
            BasicsParent.Add("http://www.sexe-rss.com/clara.html", "CHARM");
            BasicsParent.Add("http://catalog.cooklib.org/feeds/JTAdultbiographies.xml", "CHARM");
            BasicsParent.Add("http://www.adultdvdempire.com/RSSFeedPage.aspx?media_id=2&cat_id=5&s=1&cat_name=Gonzo", "CHARM");
            BasicsParent.Add("http://www.collegehumor.com/pictures/sexy/rss", "CHARM");
            BasicsParent.Add("http://feeds2.feedburner.com/BonjourMadame", "CHARM");
            BasicsParent.Add("http://www.bonjourmademoiselle.fr/rss", "CHARM");
            BasicsParent.Add("http://feeds.feedburner.com/BonjourMaman", "CHARM");
            BasicsParent.Add("http://www.bonjourmonsieur.fr/feed", "CHARM");
            BasicsParent.Add("http://lens.blogs.nytimes.com/feed/", "BLOG");
            BasicsParent.Add("http://www.blog4ever.com/rss/articles.xml", "BLOG");
            BasicsParent.Add("http://monlivre.wordpress.com/feed/", "BLOG");
            BasicsParent.Add("http://www.blog2jardinage.com/itemlist.html?format=feed&lang=fr", "BLOG");
        }
        #endregion

        #region Interface Implementations
        public bool IsFeedUpdatedSince(string feedurl, string lastpublishdate)
        {
            bool res = false;
            if (string.IsNullOrWhiteSpace(feedurl) || string.IsNullOrWhiteSpace(lastpublishdate))
            {
                ErrorStatus = "Operation Failed :(";
                return res;
            }
            using (XmlReader reader = XmlReader.Create(feedurl))
            {
                try
                {
                    SyndicationFeed feed = SyndicationFeed.Load(reader);
                    if (String.Compare(feed.LastUpdatedTime.DateTime.ToString(), lastpublishdate) != 0)
                        res = true;
                    ErrorStatus = "Operation succeed :)";
                }
                catch (Exception) { ErrorStatus = "Operation Failed :("; }
            }
            return (res);
        }

        /// <summary>
        /// Subscribe to a feed url
        /// </summary>
        /// <param name="feedurl"></param>
        /// <returns></returns>
        public Dictionary<string, string> SubscribeToFeed(string feedurl)
        {
            Dictionary<string, string> ret = new Dictionary<string, string>();

            if (string.IsNullOrWhiteSpace(feedurl)) { ErrorStatus = "Operation Failed :("; return (ret); }
            using (XmlReader reader = XmlReader.Create(feedurl))
            {
                try
                {
                    SyndicationFeed feed = SyndicationFeed.Load(reader);
                    foreach (SyndicationItem item in feed.Items)
                    {
                        ret.Add("TITLE", item.Title.Text);
                        ret.Add("LINKS", TryToDisplayLink(item.Links.ToList()));
                        ret.Add("AUTHOR", TryToDisplayAuthor(item.Authors.ToList()));
                        ret.Add("PUBLISH DATE", item.PublishDate.DateTime.DayOfWeek.ToString() + " " + item.PublishDate.DateTime.ToString());
                        ret.Add("LAST UPDATE DATE", item.LastUpdatedTime.DateTime.DayOfWeek.ToString() + " " + item.LastUpdatedTime.DateTime.ToString());
                        ret.Add("CATEGORY", TryToDisplayCategory(item.Categories.ToList()));
                        ret.Add("SUMMARY", convertsummary(item.Summary.Text));
                    }
                }
                catch (Exception) { ErrorStatus = "Operation Failed :("; }
            }
            ErrorStatus = "Operation succeed :)";
            return ret;
        }

        /// <summary>
        /// Get all saved parent feeds informations
        /// Return [Key : TITLE] [Value : LINK] by return
        /// and fill ParentfeedVsCategory with [Key : TITLE] [Value : LINK]
        /// </summary>
        /// <param name="ParentfeedVsCategory"></param>
        /// <returns></returns>
        public Dictionary<string, string> GetAllSavedParentFeeds(Dictionary<string, string> ParentfeedVsCategory)
        {
            BasicsParent = new Dictionary<string, string>();
            FillBasicsFeedsMap();
            Dictionary<string, string> ret = new Dictionary<string, string>();

            foreach (KeyValuePair<string, string> k in ret)
            {
                using (XmlReader reader = XmlReader.Create(k.Key.ToString()))
                {
                    try
                    {
                        SyndicationFeed feed = SyndicationFeed.Load(reader);
                        ret.Add(feed.Title.Text, TryToDisplayLink(feed.Links.ToList()));
                        ParentfeedVsCategory.Add(feed.Title.Text, k.Value.ToString());
                    }
                    catch (Exception) { ErrorStatus = "Operation Failed :("; }
                }
            }
            ErrorStatus = "Operation succeed :)";
            return ret;
        }

        /// <summary>
        /// Get specified parent url feed infos
        /// </summary>
        /// <param name="feedurl"></param>
        /// <param name="category"></param>
        /// <returns></returns>
        public Dictionary<string, string> GetParentFeedInfos(string feedurl, string category)
        {
            Dictionary<string, string> ret = new Dictionary<string, string>();

            if (string.IsNullOrWhiteSpace(feedurl)) { ErrorStatus = "Operation Failed :("; return (ret); }
            using (XmlReader reader = XmlReader.Create(feedurl))
            {
                try
                {
                    SyndicationFeed feed = SyndicationFeed.Load(reader);
                    ret.Add("TITLE", feed.Title.Text);
                    ret.Add("LINKS", TryToDisplayLink(feed.Links.ToList()));
                    ret.Add("LAST UPDATE DATE", feed.LastUpdatedTime.DateTime.DayOfWeek.ToString() + " " + feed.LastUpdatedTime.DateTime.ToString());
                    ret.Add("CATEGORY", category);
                    ret.Add("DESCRIPTION", convertsummary(feed.Description.Text));
                    ret.Add("AUTHOR", TryToDisplayAuthor(feed.Authors.ToList()));
                }
                catch (Exception) { ErrorStatus = "Operation Failed :("; }
            }
            ErrorStatus = "Operation succeed :)";
            return ret;
        }

        #endregion
    }
}
